//============================================================================
// Name        : cpp_time.cpp
// Author      : darkflash
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <stdio.h>
#include <sys/termios.h>
#include <cstdlib>
#include <ctime>

#include "boost/date_time/gregorian/gregorian.hpp"

#include <unistd.h>
using namespace std;

#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif

#ifndef TCSANOW
#define TCSANOW 0
#endif

struct termios t;

void fnPrintMode()
{
	cout << "1. last day" << endl;
	cout << "2. last day(boost)" << endl;
	cout << "3. sleep" << endl;
	cout << "4. yoon year" << endl;
	cout << "5. time2string" << endl;
	cout << "q. quit" << endl;
}

void fnOffBufferedInput()
{
	tcgetattr(STDIN_FILENO, &t); //get the current terminal I/O structure
	t.c_lflag &= ~ICANON; //Manipulate the flag bits to do what you want it to do
	tcsetattr(STDIN_FILENO, TCSANOW, &t); //Apply the new settings
}

void fnOnBufferedInput()
{
	tcgetattr(STDIN_FILENO, &t); //get the current terminal I/O structure
	t.c_lflag |= ICANON; //Manipulate the flag bits to do what you want it to do
	tcsetattr(STDIN_FILENO, TCSANOW, &t); //Apply the new settings
}

int getch(void)
{
	fnOffBufferedInput();
	int ch = getchar(); /* standard getchar call */
	fnOnBufferedInput();
	return ch; /*return received char */
}

int fnLastday(int year, int month)
{
	int rtn = 0;

	struct tm when;
	time_t lastday;

	time(&lastday);
	when = *localtime(&lastday);

	// Set up current month
	when.tm_hour = 0;
	when.tm_min = 0;
	when.tm_sec = 0;
	when.tm_mday = 1;

	// Next month 0=Jan
	if (month == 12)
	{
		when.tm_mon = 0;
		when.tm_year = year - 1900 + 1;
	}
	else
	{
		when.tm_mon = month;
		when.tm_year = year - 1900;
	}

	// Get the first day of the next month
	lastday = mktime (&when);

	cout << lastday << endl;

	// Subtract 1 day
	lastday -= (24*60*60);

	// Convert back to date and time
	when = *localtime (&lastday);
	rtn = when.tm_mday;

	return rtn;
}

void fnLastdayMode()
{
	string input_year, input_month;

	cout << "input year: ";
	cin >> input_year;
	getchar();

	cout << "input month: ";
	cin >> input_month;
	getchar();

	int lastday = fnLastday(atoi(input_year.c_str()), atoi(input_month.c_str()));
	cout << lastday << endl;
}

int fnLastdayBoost(int year, int month)
{
	int rtn = 0;

	using namespace boost::gregorian;

	greg_year g_year(year);
	greg_month g_month(month);

	date d(year, month, 1);
	rtn = gregorian_calendar::end_of_month_day(g_year, g_month);

	return rtn;
}

void fnLastdayBoostMode()
{
	string input_year, input_month;

	cout << "input year: ";
	cin >> input_year;
	getchar();

	cout << "input month: ";
	cin >> input_month;
	getchar();

	int lastday = fnLastdayBoost(atoi(input_year.c_str()), atoi(input_month.c_str()));
	cout << lastday << endl;
}

void fnSleep(int delay)
{
	sleep(delay);
}

void fnSleepMode()
{
	string input_delay;

	cout << "input delay: ";
	cin >> input_delay;
	getchar();

	time_t now;

	time(&now);
	cout << now << endl;

	fnSleep(atoi(input_delay.c_str()));

	time(&now);
	cout << now << endl;
}

bool fnYoonYear(int year)
{
	bool rtn = false;

	using namespace boost::gregorian;

	greg_year g_year(year);
	rtn = gregorian_calendar::is_leap_year(g_year);

	return rtn;
}

void fnYoonYearMode()
{
	string input_year;

	cout << "input year: ";
	cin >> input_year;
	getchar();

	bool yoonYear = fnYoonYear(atoi(input_year.c_str()));

	cout << yoonYear << endl;
}

string fnTime2String(time_t time)
{
	string rtn = "";
	struct tm* date;

	date = localtime(&time);

	char buffer[80];
	strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", date);
	rtn = string(buffer);

	return rtn;
}

void fnTime2StringMode()
{
	time_t now;
	time(&now);

	string time2String = fnTime2String(now);

	cout << time2String << endl;
}

int main() {
	int input_mode;

	do{
		fnPrintMode();
		input_mode = getch();
		cout << endl;
		switch(input_mode){
		case '1':
			fnLastdayMode();
			break;
		case '2':
			fnLastdayBoostMode();
			break;
		case '3':
			fnSleepMode();
			break;
		case '4':
			fnYoonYearMode();
			break;
		case '5':
			fnTime2StringMode();
			break;
		}
		cin.clear();
		fflush(stdin);
	}while(input_mode != 'q');

	return 0;
}
